"use strict";
// 卡片
let ECard = function (selector, options) {
    // 目标元素
    let the = this;

    // 查找对象
    let $element = $(selector);
    let element = $element[0];
    let $body = $('body');

    let stickyClass = 'card--sticky';

    if (!element) {
        return;
    }

    // 默认设置
    let defaultOptions = {
        bodyToggleSpeed: 400,
        tooltips: true,
        tools: {
            toggle: {
                collapse: {
                    text: '折叠',
                    icon: 'la la-angle-up'
                },
                expand: {
                    text: '展开',
                    icon: 'la la-angle-down'
                }
            },
            reload: '刷新',
            remove: '移除',
            fullscreen: {
                on: {
                    text: '全屏',
                    icon: 'la la-compress'
                },
                off: {
                    text: '退出全屏',
                    icon: 'la la-expand'
                }
            }
        },
        sticky: {
            offset: 300,
            zIndex: 101
        }
    };

    // 私有方法
    let Plugin = {
        construct: function (options) {
            if (EUtil.data(element).has('card')) {
                the = EUtil.data(element).get('card');
            } else {
                // 初始化
                Plugin.init(options);

                // 构建
                Plugin.build();

                EUtil.data(element).set('card', the);
            }

            return the;
        },

        /**
         * 初始化
         */
        init: function (options) {
            the.element = element;
            the.events = [];

            // 合并默认选项&传入option
            the.options = $.extend(true, {}, defaultOptions, options);
            // head body foot
            the.head = $element.find('.card-head');
            the.body = $element.find('.card-body');
            the.foot = $element.find('.card-foot');
        },

        /**
         * 构建
         */
        build: function () {
            // 绑定 展开/折叠、刷新、删除、全屏/退出全屏 事件
            the.head.find('[data-card-tool="toggle"], [data-card-tool=reload], [data-card-tool=remove], [data-card-tool=fullscreen]').click(function (e) {
                e.preventDefault();
                let method = $(this).data('card-tool');
                Plugin[method].call();
            });
            // 设置tooltips
            Plugin.setupTooltips();
        },

        /**
         * 初始化固定头部
         */
        initSticky: function () {
            if (the.head.length) {
                window.addEventListener('scroll', Plugin.onScrollSticky);
            }
        },

        /**
         * 当滚动到头部时将头部固定在顶部，一般用于头部有操作按钮的卡片
         * 注：仅支持页面中只有一个card的场景
         */
        onScrollSticky: function (e) {
            let offset = the.options.sticky.offset;
            if (isNaN(offset)) return;
            // 页面往上滚动的距离
            let st = document.documentElement.scrollTop;

            if (st >= offset && !$body.hasClass(stickyClass)) {
                Plugin.eventTrigger('stickyOn');
                $body.addClass(stickyClass);
                $element.addClass(stickyClass);
                Plugin.updateSticky();

            } else if ((st * 1.5) <= offset && $body.hasClass(stickyClass)) {
                // 往上滚动到offset，取消固定
                Plugin.eventTrigger('stickyOff');
                $body.removeClass(stickyClass);
                $element.removeClass(stickyClass);
                Plugin.resetSticky();
            }
        },

        updateSticky: function () {
            if (the.head.length) {
                let top;

                if ($body.hasClass(stickyClass)) {
                    if (the.options.sticky.position.top instanceof Function) {
                        top = parseInt(the.options.sticky.position.top.call());
                    } else {
                        top = parseInt(the.options.sticky.position.top);
                    }

                    let left;
                    if (the.options.sticky.position.left instanceof Function) {
                        left = parseInt(the.options.sticky.position.left.call());
                    } else {
                        left = parseInt(the.options.sticky.position.left);
                    }

                    let right;
                    if (the.options.sticky.position.right instanceof Function) {
                        right = parseInt(the.options.sticky.position.right.call());
                    } else {
                        right = parseInt(the.options.sticky.position.right);
                    }
                    the.head.css({
                        zIndex: the.options.sticky.zIndex,
                        top: top,
                        left: left,
                        right: right
                    });
                }
            }
        },
        /**
         * 取消固定
         */
        resetSticky: function () {
            if (the.head.length && !$body.hasClass(stickyClass)) {
                the.head.css({
                    zIndex: '',
                    top: '',
                    left: '',
                    right: ''
                });
            }
        },

        /**
         * 删除卡片
         */
        remove: function () {
            // 删除前回调
            if (Plugin.eventTrigger('beforeRemove') === false) {
                return;
            }

            if ($body.hasClass('card--fullscreen') && $element.hasClass('card--fullscreen')) {
                // 如果处于全屏状态，退出全屏
                Plugin.fullscreen('off');
            }

            Plugin.removeTooltips();

            $element.remove();
            // 删除后回调
            Plugin.eventTrigger('afterRemove');
        },

        /**
         * 设置 tooltips
         */
        setupTooltips: function () {
            // 公用属性
            let commonOption = {};
            /**
             *
             * @param _selector {string} 选择器
             * @param title {string} 标题
             */
            let initTooltip = function (_selector, title) {
                let $target = the.head.find(_selector);
                if ($target.length) {
                    let tip = new Tooltip($target, $.extend(true, {}, commonOption, {
                        title: title
                    }));
                    EUtil.data($target).set('tooltip', tip);
                }
            };

            if (the.options.tooltips) {
                // 是否为折叠状态
                let collapsed = $element.hasClass('card--collapse') || $element.hasClass('card--collapsed');
                // 是否为全屏状态
                let fullscreenOn = $body.hasClass('card--fullscreen') && $element.hasClass('card--fullscreen');
                // 方向
                let placement = fullscreenOn ? 'bottom' : 'top';
                // 公用属性
                commonOption = {
                    placement: placement,
                    offset: fullscreenOn ? '0,10px,0,0' : '0,5px',
                    trigger: 'hover',
                    template: '<div class="tooltip tooltip-card tooltip bs-tooltip-' + placement + '" role="tooltip">\
                            <div class="tooltip-arrow arrow"></div>\
                            <div class="tooltip-inner"></div>\
                        </div>'
                };
                // 展开/折叠
                initTooltip('[data-card-tool=toggle]', collapsed ? the.options.tools.toggle.expand.text : the.options.tools.toggle.collapse.text);
                //刷新
                initTooltip('[data-card-tool=reload]', the.options.tools.reload);
                //删除
                initTooltip('[data-card-tool=remove]', the.options.tools.remove);
                //全屏/退出全屏
                initTooltip('[data-card-tool=fullscreen]', (fullscreenOn ? the.options.tools.fullscreen.off.text : the.options.tools.fullscreen.on.text));
            }
        },

        /**
         * 删除 tooltips
         */
        removeTooltips: function () {
            if (the.options.tooltips) {
                the.head.find('[data-card-tool="toggle"], [data-card-tool=reload], [data-card-tool=remove], [data-card-tool=fullscreen]').each(function () {
                    let tip = EUtil.data(this).get('tooltip');
                    if (tip) {
                        tip.dispose();
                    }
                });
            }
        },

        /**
         * 刷新
         */
        reload: function () {
            Plugin.eventTrigger('reload');
        },

        /**
         * 展开/折叠
         */
        toggle: function () {
            if ($element.hasClass('card--collapse') || $element.hasClass('card--collapsed')) {
                Plugin.expand();
            } else {
                Plugin.collapse();
            }
        },

        /**
         * 折叠
         */
        collapse: function () {
            if (Plugin.eventTrigger('beforeCollapse') === false) {
                // 回调函数不允许折叠
                return;
            }

            the.body.slideUp(the.options.bodyToggleSpeed, function () {
                Plugin.eventTrigger('afterCollapse');
            });
            $element.addClass('card--collapse');

            if (the.options.tooltips) {
                let $toggle = the.head.find('[data-card-tool=toggle]');
                if ($toggle.length && EUtil.data($toggle).has('tooltip')) {
                    EUtil.data($toggle).get('tooltip').updateTitleContent(the.options.tools.toggle.expand);
                    $toggle.find('i').removeClass().addClass(the.options.tools.toggle.expand.icon);
                }
            }
        },

        /**
         * 展开
         */
        expand: function () {
            if (Plugin.eventTrigger('beforeExpand') === false) {
                // 回调函数不允许展开
                return;
            }

            the.body.slideDown(the.options.bodyToggleSpeed, function () {
                Plugin.eventTrigger('afterExpand');
            });
            $element.removeClass('card--collapse card--collapsed');

            if (the.options.tooltips) {
                let $toggle = the.head.find('[data-card-tool=toggle]');
                if ($toggle.length && EUtil.data($toggle).has('tooltip')) {
                    EUtil.data($toggle).get('tooltip').updateTitleContent(the.options.tools.toggle.collapse.text);
                    $toggle.find('i').removeClass().addClass(the.options.tools.toggle.collapse.icon);
                }
            }
        },

        /**
         * 全屏/退出全屏
         *
         * @param mode {string} on | off
         */
        fullscreen: function (mode) {
            if (!mode) {
                mode = $body.hasClass('card--fullscreen') ? 'off' : 'on';
            }

            if ('off' === mode || ($body.hasClass('card--fullscreen') && $element.hasClass('card--fullscreen'))) {
                Plugin.eventTrigger('beforeFullscreenOff');

                $body.removeClass('card--fullscreen');
                $element.removeClass('card--fullscreen');

                // Plugin.removeTooltips();
                // Plugin.setupTooltips();

                if (the.foot.length) {
                    the.foot.css({
                        marginBottom: '',
                        marginTop: ''
                    });
                }

                Plugin.eventTrigger('afterFullscreenOff');
            } else {
                Plugin.eventTrigger('beforeFullscreenOn');

                $element.addClass('card--fullscreen');
                $body.addClass('card--fullscreen');

                // Plugin.removeTooltips();
                // Plugin.setupTooltips();

                if (the.foot.length) {
                    let footHeight = the.foot.height();
                    let height = footHeight + the.head.height();
                    the.body.css('margin-bottom', footHeight);
                    the.foot.css('margin-top', height);
                }
                Plugin.eventTrigger('afterFullscreenOn');
            }

            if (the.options.tooltips) {
                let $fullscreen = the.head.find('[data-card-tool=fullscreen]');
                if ($fullscreen.length && EUtil.data($fullscreen).has('tooltip')) {
                    EUtil.data($fullscreen).get('tooltip').updateTitleContent(the.options.tools.fullscreen[mode].text);
                    $fullscreen.find('i').removeClass().addClass(the.options.tools.fullscreen[mode].icon);
                }
            }
        },
        /**
         * Set content
         */
        setContent: function (html) {
            the.body.html(html);
        },

        /**
         * Get body
         */
        getBody: function () {
            return the.body;
        },

        /**
         * Get self
         */
        getSelf: function () {
            return element;
        },

        /**
         * 触发事件
         *
         * @param name {string} 事件名称
         * @param args {object} 参数
         */
        eventTrigger: function (name, args) {
            for (let i = 0; i < the.events.length; i++) {
                let event = the.events[i];
                if (event.name === name) {
                    if (event.one) {
                        // 一次性事件
                        if (!event.fired) {
                            // 设置事件属性为已触发，下次不执行
                            the.events[i].fired = true;
                            event.handler.call(this, the, args);
                        }
                    } else {
                        event.handler.call(this, the, args);
                    }
                }
            }
        },

        /**
         * 添加事件
         *
         * @param name {string} 事件名称
         * @param handler {function} 回调
         * @param one {boolean} 是否一次性
         */
        addEvent: function (name, handler, one) {
            the.events.push({
                name: name,
                handler: handler,
                one: one,
                fired: false
            });
        }
    };

    // 公开方法

    /**
     * 设置默认option
     *
     * @param options {object} 选项
     */
    the.setDefaults = function (options) {
        defaultOptions = options;
    };

    /**
     * 删除卡片
     * @returns {ECard}
     */
    the.remove = function () {
        return Plugin.remove();
    };

    /**
     * 初始化固定头部
     * @returns {ECard}
     */
    the.initSticky = function () {
        return Plugin.initSticky();
    };

    /**
     * 更新固定头部
     * @returns {ECard}
     */
    the.updateSticky = function () {
        return Plugin.updateSticky();
    };

    /**
     * 重置固定头部
     * @returns {ECard}
     */
    the.resetSticky = function () {
        return Plugin.resetSticky();
    };

    /**
     * 销毁固定头部
     */
    the.destroySticky = function () {
        Plugin.resetSticky();
        window.removeEventListener('scroll', Plugin.onScrollSticky);
    };

    /**
     * 刷新
     * @returns {ECard}
     */
    the.reload = function () {
        return Plugin.reload();
    };

    /**
     * 设置内容
     *
     * @param html {string} 内容
     * @returns {ECard}
     */
    the.setContent = function (html) {
        return Plugin.setContent(html);
    };

    /**
     * 切换展开/折叠卡片
     * @returns {ECard}
     */
    the.toggle = function () {
        return Plugin.toggle();
    };

    /**
     * 折叠卡片
     *
     * @returns {ECard}
     */
    the.collapse = function () {
        return Plugin.collapse();
    };

    /**
     * 展开卡片
     * @returns {ECard}
     */
    the.expand = function () {
        return Plugin.expand();
    };

    /**
     * 全屏
     * @returns {ECard}
     */
    the.fullscreen = function () {
        return Plugin.fullscreen('on');
    };

    /**
     * 退出全屏
     * @returns {ECard}
     */
    the.unFullscreen = function () {
        return Plugin.fullscreen('off');
    };

    /**
     * 获取body
     * @returns {jQuery}
     */
    the.getBody = function () {
        return Plugin.getBody();
    };

    /**
     * 获取card
     * @returns {jQuery}
     */
    the.getSelf = function () {
        return Plugin.getSelf();
    };

    /**
     * 绑定事件
     *
     * @param name {string} 事件名称
     * @param handler {function} 回调
     * @returns {*|void}
     */
    the.on = function (name, handler) {
        return Plugin.addEvent(name, handler, false);
    };
    /**
     * 绑定一次性事件
     *
     * @param name {string} 事件名称
     * @param handler {function} 回调
     * @returns {*|void}
     */
    the.one = function (name, handler) {
        return Plugin.addEvent(name, handler, true);
    };

    // Construct plugin
    Plugin.construct.apply(the, [options]);

    return the;
};